﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using io = System.IO;
using wf = System.Windows.Forms;
using System.Threading;
using dw = System.Drawing;

namespace editor.app
{
    /// <summary>
    /// StarWindow.xaml 的交互逻辑
    /// </summary>
    public partial class StarWindow : Window
    {
        #region LayerType
        enum LayerType
        {
            背景 = 1,
            网格 = 3,
            拖动1 = 2,
            拖动2 = 4,
            中心点 = 12,
            编号 = 5,
            阵营关系 = 7,
            地图关系 = 9,
            空间关系 = 11,
        }
        #endregion

        #region Block
        public class Block
        {
            public static Polygon MakePath(List<int[]> pathList)
            {
                var points = new PointCollection();
                foreach (var item in pathList)
                {
                    points.Add(new Point(item[0], item[1]));
                }
                return new Polygon { Points = points };
            }
            static Dictionary<string, Color> _spaceTypeColorDic = new Dictionary<string, Color>();
            static Color GetColor(string type)
            {
                if (_spaceTypeColorDic.ContainsKey(type))
                {
                    return _spaceTypeColorDic[type];
                }
                return Color2.Yellow();
            }
            static Block()
            {
                _spaceTypeColorDic.Add(comm.objst.SpaceType.FAC_SAFETY.ToString(), Color2.Green(30));
                _spaceTypeColorDic.Add(comm.objst.SpaceType.FAC_WAR.ToString(), Color2.Black(30));
                _spaceTypeColorDic.Add(comm.objst.SpaceType.ALL_FAC_SAFETY.ToString(), Color2.Orange(30));
            }

            public Area _area = null;
            public comm.objst.DStar.Data.Space _space = null;
            int _x = 0, _y = 0;
            Canvas _cvRoot = new Canvas();
            Canvas _cvPath = new Canvas();
            Canvas _cvDot = new Canvas();
            Canvas _cvDot2 = new Canvas();
            Canvas _cvDot3 = new Canvas();


            int DOT_SIZE = 16;
            MenuItem _mSpaceType = null;
            Grid _grid = null;
            public Border _brDot2 = null;
            public comm.objst.DMap.Data _map = null;
            List<comm.lib.MapEvent> _links = new List<comm.lib.MapEvent>();

            public Block(Area area, int x, int y)
            {
                _area = area;
                _x = x;
                _y = y;
                _space = _area._area.Spaces[_x, _y];

                _map = App.DefineFile.GetMapData(_space.MapId);
                if (_map != null)
                {
                    _map.AddExObjDic(_space.ObjDic);
                }

                _cvRoot.MouseEnter += new MouseEventHandler(_cvRoot_MouseEnter);
                _area._cvLayer.Children.Add(_cvRoot);

                #region Space Link
                if (_map != null)
                {
                    foreach (var obj in _map.ObjDic.Values)
                    {
                        if (obj is comm.objst.DMap.Data.SObj)
                        {
                            var sobj = (comm.objst.DMap.Data.SObj)obj;
                            var m1 = sobj.FindEV<comm.lib.MapEvent.MoveToSpace>();
                            var m2 = sobj.FindEV<comm.lib.MapEvent.MoveToLocLabel>();
                            if (m1 != null)
                            {
                                _links.Add(m1);
                            }
                            else if (m2 != null)
                            {
                                _links.Add(m2);
                            }
                        }
                    }
                }
                #endregion
            }

            void _cvRoot_MouseEnter(object sender, MouseEventArgs e)
            {
                Light();

                _area._window.BlockEnter(this);
            }
            void contextMenu_Opened(object sender, RoutedEventArgs e)
            {
                _mSpaceType.Items.Clear();
                var types = comm.objst.DStar.Data.GetSpaceTypes();
                foreach (var type in types)
                {
                    var tb = new TextBlock
                    {
                        Text = type,
                        Foreground = new SolidColorBrush(Color2.FromColor(255, GetColor(type)))
                    };
                    var mi = new MenuItem
                    {
                        Header = new Border
                        {
                            Child = tb,
                            Background = new SolidColorBrush(Color2.Black(type == _space.SpaceType.ToString() ? 80 : 30))
                        },
                        Tag = type
                    };
                    mi.Click += new RoutedEventHandler(miSpaceType_Click);
                    _mSpaceType.Items.Add(mi);
                }
            }
            void miSpaceType_Click(object sender, RoutedEventArgs e)
            {
                var mi = (MenuItem)sender;
                var type = comm.EnumHelper.Parse<comm.objst.SpaceType>(mi.Tag.ToString());
                _space.SpaceType = type;
                _area._window.Fill();
            }
            void LayerDrag(FrameworkElement sender, MouseEventArgs e, string type, double ox, double oy)
            {
                if (type == "move")
                {
                    var pt = e.GetPosition(_cvRoot);
                    double x = pt.X - ox, y = pt.Y - oy;
                    var br = (Border)sender;
                    var ix = (int)br.Tag;
                    var dot = _space.PathList[ix];

                    _area.SetSpaceLoc(dot[0], dot[1], (int)pt.X, (int)pt.Y);
                }
                e.Handled = true;
            }
            void CentreDotDrag(FrameworkElement sender, MouseEventArgs e, string type, double ox, double oy)
            {
                if (type == "move")
                {
                    var pt = e.GetPosition(_cvRoot);
                    double x = pt.X - ox, y = pt.Y - oy;
                    var br = (Border)sender;
                    br.SetLeftTop(x, y);

                    _space.CentreX = (int)x + 16 / 2;
                    _space.CentreY = (int)y + 16 / 2;
                }
                e.Handled = true;
            }

            public void Draw()
            {
                _cvRoot.Children.Clear();

                var mapSize = _area._area.MapSize;
                var mapBlockSize = _area._area.MapBlockSize; ;

                if (_area._window.CanDisplay(LayerType.网格))
                {
                    #region bg
                    var brBG = new Border
                    {
                        Width = mapSize,
                        Height = mapSize,
                        BorderBrush = new SolidColorBrush(Color2.White(10)),
                        BorderThickness = new Thickness(0, 0, 1, 1)
                    };
                    brBG.SetLeftTop(_x * mapSize, _y * mapSize);
                    _cvRoot.Children.Add(brBG);
                    #endregion
                }

                DrawPath();

                _cvRoot.Children.Add(_cvPath);

                _grid = new Grid { Width = mapSize, Height = mapSize };
                _grid.SetLeftTop(_x * mapSize, _y * mapSize);
                TextBlock.SetFontFamily(_grid, new FontFamily("SimSun"));
                TextOptions.SetTextFormattingMode(_grid, TextFormattingMode.Display);

                if (_area._window.CanDisplay(LayerType.编号))
                {
                    #region grid
                    var mapOK = App.DefineFile.GetMap(_space.MapId) != null;
                    _grid.Children.Add(new Border
                    {
                        CornerRadius = new CornerRadius(2),
                        Padding = new Thickness(2, 0, 2, 0),
                        VerticalAlignment = VerticalAlignment.Center,
                        HorizontalAlignment = HorizontalAlignment.Center,
                        Child = new TextBlock
                        {
                            FontSize = 12,
                            Foreground = new SolidColorBrush(Color2.White()),
                            Text = _space.SpaceId + "" + (mapOK ? "(" + _space.ObjDic.Count + ")" : "")
                        },
                        Background = new SolidColorBrush(Color2.Black(50)),
                        Opacity = mapOK ? 1 : .3
                    });
                    #endregion
                }
                _cvRoot.Children.Add(_grid);

                if (_area._window.CanDisplay(LayerType.拖动1))
                {
                    #region drag dot1
                    for (int i = 0, len = _space.PathList.Count; i < len; i++)
                    {
                        var item = _space.PathList[i];
                        var brDot = new Border
                        {
                            Width = DOT_SIZE,
                            Height = DOT_SIZE,
                            Tag = i,
                            CornerRadius = new CornerRadius(DOT_SIZE),
                            Background = new SolidColorBrush(Color2.White(10)),
                            BorderBrush = new SolidColorBrush(Color2.Black(70)),
                            BorderThickness = new Thickness(1),
                        };
                        brDot.MouseEnter += new MouseEventHandler((o, e) =>
                        {
                            brDot.BorderThickness = new Thickness(2);
                            brDot.BorderBrush = new SolidColorBrush(Color2.Yellow());
                        });
                        brDot.MouseLeave += new MouseEventHandler((o, e) =>
                        {
                            brDot.BorderThickness = new Thickness(1);
                            brDot.BorderBrush = new SolidColorBrush(Color2.Black(70));
                        });
                        brDot.Drag(LayerDrag);
                        brDot.SetLeftTop(item[0] - DOT_SIZE / 2, item[1] - DOT_SIZE / 2);
                        _cvDot.Children.Add(brDot);

                    }
                    #endregion
                }
                _cvRoot.Children.Add(_cvDot);

                if (_area._window.CanDisplay(LayerType.拖动2))
                {
                    #region drag dot2
                    var dotSize = 16;
                    _brDot2 = new Border
                    {
                        Margin = new Thickness(4, 4, 0, 0),
                        Width = dotSize,
                        Height = dotSize,
                        CornerRadius = new CornerRadius(dotSize),
                        Background = new SolidColorBrush(Color2.Black(30)),
                        BorderBrush = new SolidColorBrush(Color2.Yellow(70)),
                        BorderThickness = new Thickness(1),
                    };
                    _brDot2.MouseDown += new MouseButtonEventHandler((o, e) =>
                    {
                        e.Handled = true;
                        _area._window.BlockClick(this);
                    });
                    _brDot2.MouseEnter += new MouseEventHandler((o, e) =>
                    {
                        _brDot2.Background = new SolidColorBrush(Color2.Black(60));
                        _brDot2.BorderBrush = new SolidColorBrush(Color2.Yellow());
                    });
                    _brDot2.MouseLeave += new MouseEventHandler((o, e) =>
                    {
                        _brDot2.Background = new SolidColorBrush(Color2.Black(30));
                        _brDot2.BorderBrush = new SolidColorBrush(Color2.Yellow(70));
                    });
                    _brDot2.SetLeftTop(_x * mapSize, _y * mapSize);
                    _cvDot2.Children.Add(_brDot2);
                    #endregion
                }
                _cvRoot.Children.Add(_cvDot2);

                if (_area._window.CanDisplay(LayerType.中心点))
                {
                    #region drag brDot
                    var dotSize = 16;
                    var brDot = new Border
                    {
                        Width = dotSize,
                        Height = dotSize,
                        CornerRadius = new CornerRadius(dotSize),
                        Background = new SolidColorBrush(Color2.Black(30)),
                        BorderBrush = new SolidColorBrush(Color2.Red(70)),
                        BorderThickness = new Thickness(1),
                    };
                    brDot.MouseEnter += new MouseEventHandler((o, e) =>
                    {
                        brDot.Background = new SolidColorBrush(Color2.Black(60));
                        brDot.BorderBrush = new SolidColorBrush(Color2.Red());
                    });
                    brDot.MouseLeave += new MouseEventHandler((o, e) =>
                    {
                        brDot.Background = new SolidColorBrush(Color2.Black(30));
                        brDot.BorderBrush = new SolidColorBrush(Color2.Red(70));
                    });
                    if (_space.CentreX == 0 && _space.CentreY == 0)
                    {
                        var pt = GetPosition();
                        _space.CentreX = _x * mapSize + 20 - dotSize / 2;
                        _space.CentreY = _y * mapSize + 20 - dotSize / 2;
                    }

                    brDot.SetLeftTop(_space.CentreX - dotSize / 2, _space.CentreY - dotSize / 2);
                    brDot.Drag(CentreDotDrag);
                    _cvDot3.Children.Add(brDot);
                    #endregion
                }
                else
                {
                    var brDot = new Border
                    {
                        Width = 10,
                        Height = 10,
                        CornerRadius = new CornerRadius(10),
                        Background = new SolidColorBrush(Color2.Black(50)),
                        BorderBrush = new SolidColorBrush(Color2.Black()),
                        BorderThickness = new Thickness(1),
                    };
                    brDot.SetLeftTop(_space.CentreX - 10 / 2, _space.CentreY - 10 / 2);
                    _cvDot3.Children.Add(brDot);
                }
                _cvRoot.Children.Add(_cvDot3);

                #region contextMenu
                var contextMenu = new ContextMenu { FontSize = 14 };
                contextMenu.Opened += new RoutedEventHandler(contextMenu_Opened);
                TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);

                _mSpaceType = new MenuItem { Header = "类型" };
                contextMenu.Items.Add(_mSpaceType);

                var map = App.DefineFile.GetMap(_space.MapId);

                #region mEditMap, mSpaceLink
                var mEditMap = new MenuItem
                {
                    IsEnabled = false,
                    Header = new TextBlock { Text = "Edit Map" }
                };
                var mSpaceLink = new MenuItem
                {
                    IsEnabled = false,
                    Header = new TextBlock { Text = "Space Link(Round)" }
                };
                if (map != null)
                {
                    mEditMap.IsEnabled = true;
                    mEditMap.Click += new RoutedEventHandler((o, e) =>
                    {
                        var window = new MapWindow(map.File, _space.ObjDic, _space.PathList);
                        window.OnSaveCallback = dic =>
                        {
                            _space.ObjDic.Clear();
                            foreach (var objKey in dic.Keys)
                            {
                                _space.ObjDic.Add(objKey, dic[objKey]);
                            }
                        };
                        window.ShowDialog();
                        _area._window.Fill();
                    });

                    mSpaceLink.IsEnabled = true;
                    mSpaceLink.Click += new RoutedEventHandler((o, e) =>
                    {
                        var rect = new Rect(0, 0, _area._area.Width - 1, _area._area.Height - 1);
                        var dots = comm.MathHelper.FillRect(_x - 1, _y - 1, 3, 3);
                        var spaces = new comm.objst.DStar.Data.Space[3, 3];
                        foreach (var dot in dots)
                        {
                            if (rect.Contains(dot[0], dot[1]))
                            {
                                spaces[dot[0] - _x + 1, dot[1] - _y + 1] = _area._blocks[dot[0], dot[1]]._space;
                            }
                        }
                        new SpaceLinkWindow(3, 3, spaces).ShowDialog();
                    });
                }
                contextMenu.Items.Add(mSpaceLink);
                contextMenu.Items.Add(mEditMap);
                #endregion

                #region mClearMapId
                var mClearMapId = new MenuItem { Header = new TextBlock { Text = "删除MapId" } };
                mClearMapId.Click += new RoutedEventHandler((o, e) =>
                {
                    _space.MapId = "";
                    _area._window.Fill();
                });
                contextMenu.Items.Add(mClearMapId);
                #endregion

                contextMenu.Items.Add(new Separator());

                #region mAllSpaceType
                var mAllSpaceType = new MenuItem { Header = new TextBlock { Text = "All类型" } };
                var types = comm.objst.DStar.Data.GetSpaceTypes();
                foreach (var type in types)
                {
                    var type2 = type;
                    var mi = new MenuItem { Header = new TextBlock { Text = type } };
                    mi.Click += new RoutedEventHandler((o, e) =>
                    {
                        var type3 = comm.EnumHelper.Parse<comm.objst.SpaceType>(type2);
                        _area.SetAllSpaceType(type3);
                    });
                    mAllSpaceType.Items.Add(mi);
                }
                contextMenu.Items.Add(mAllSpaceType);
                #endregion

                #region mClearAllMapId
                var mClearAllMapId = new MenuItem { Header = new TextBlock { Text = "清空AllMapId" } };
                mClearAllMapId.Click += new RoutedEventHandler((o, e) =>
                {
                    _area.ClearAllMapId();
                });
                contextMenu.Items.Add(mClearAllMapId);
                #endregion

                #region set bg
                var mSetAreaBG = new MenuItem { Header = new TextBlock { Text = "设置Area背景" } };
                mSetAreaBG.Click += new RoutedEventHandler((o, e) =>
                {
                    _area.SetBG();
                });
                contextMenu.Items.Add(mSetAreaBG);
                #endregion

                #region editArea
                var mEditArea = new MenuItem { Header = new TextBlock { Text = "编辑Area" } };
                mEditArea.Click += new RoutedEventHandler((o, e) =>
                {
                    _area.ReceiveCmd("editArea");
                });
                contextMenu.Items.Add(mEditArea);
                #endregion

                _cvRoot.ContextMenu = contextMenu;
                #endregion
            }
            public void DrawPath()
            {
                _cvPath.Children.Clear();
                var brs = _cvDot.Children;

                var ix = -1;
                foreach (var item in _space.PathList)
                {
                    ix++;
                    if (brs.Count > 0)
                    {
                        ((FrameworkElement)brs[ix]).SetLeftTop(item[0] - DOT_SIZE / 2, item[1] - DOT_SIZE / 2);
                    }
                }
                var path = MakePath();
                path.Fill = new SolidColorBrush(GetColor(_space.SpaceType.ToString()));
                path.Stroke = new SolidColorBrush(Color2.White(70));
                path.StrokeThickness = 1;
                _cvPath.Children.Add(path);
            }
            public bool PointInPolygon(int x, int y)
            {
                var pt = _area.GetPosition();
                var dots = new List<dw.Point>();
                foreach (var item in _space.PathList)
                {
                    dots.Add(new dw.Point(item[0] + (int)pt.X, item[1] + (int)pt.Y));
                }
                var path = new dw.Drawing2D.GraphicsPath();
                var region = new dw.Region();
                path.Reset();
                path.AddPolygon(dots.ToArray());
                region.MakeEmpty();
                region.Union(path);
                return region.IsVisible(new dw.Point(x, y));
            }
            public Point GetPosition()
            {
                return _grid.TranslatePoint(new Point(), _area._window.gridRoot);
            }
            public void Light()
            {
                _area._cvMask.Children.Clear();
                if (!_area._window.CanDisplay(LayerType.拖动1))
                {
                    var path = MakePath();
                    path.Stroke = new SolidColorBrush(Color2.Yellow());
                    path.StrokeThickness = 2;
                    _area._cvMask.Children.Add(path);
                }
            }
            public void SetMap(string mapId)
            {
                _space.MapId = mapId;
            }
            public Polygon MakePath()
            {
                return MakePath(_space.PathList);
            }
            public void LinkSpace(Canvas cv)
            {
                if (_links.Count > 0)
                {
                    var ix = 0;
                    foreach (var ev in _links)
                    {
                        if (ev is comm.lib.MapEvent.MoveToSpace)
                        {
                            #region MoveToSpace
                            var e = (comm.lib.MapEvent.MoveToSpace)ev;
                            if (_area._window._blockDic.ContainsKey(e.SpaceId))
                            {
                                var block2 = _area._window._blockDic[e.SpaceId];
                                var pt1 = GetPosition();
                                var pt2 = block2.GetPosition();
                                cv.Children.Add(new Line
                                {
                                    X1 = pt1.X + _area._area.MapSize / 2 + ix,
                                    Y1 = pt1.Y + _area._area.MapSize / 2 + ix,
                                    X2 = pt2.X + block2._area._area.MapSize / 2 + ix,
                                    Y2 = pt2.Y + block2._area._area.MapSize / 2 + ix,
                                    Stroke = new SolidColorBrush(Color2.LightSkyBlue(80)),
                                    StrokeThickness = 2
                                });
                                ix += 2;
                            }
                            #endregion
                        }
                        else if (ev is comm.lib.MapEvent.MoveToLocLabel)
                        {
                            #region MoveToLocLabel
                            var e = (comm.lib.MapEvent.MoveToLocLabel)ev;
                            if (_area._window._blockDic.ContainsKey(e.SpaceId))
                            {
                                var block2 = _area._window._blockDic[e.SpaceId];
                                if (block2._map != null && block2._map.ObjDic.ContainsKey(e.MapObjKey))
                                {
                                    var obj2 = block2._map.ObjDic[e.MapObjKey];
                                    if (obj2 is comm.objst.DMap.Data.SObj)
                                    {
                                        var sobj = (comm.objst.DMap.Data.SObj)obj2;
                                        var cmd = sobj.FindEV<comm.lib.MapEvent.Command>();
                                        if (cmd != null && cmd.Type == comm.lib.MapEvent.CommandType.LOC_LABEL)
                                        {
                                            var pt1 = GetPosition();
                                            var pt2 = block2.GetPosition();
                                            cv.Children.Add(new Line
                                            {
                                                X1 = pt1.X + _area._area.MapSize / 2 + ix,
                                                Y1 = pt1.Y + _area._area.MapSize / 2 + ix,
                                                X2 = pt2.X + block2._area._area.MapSize / 2 + ix,
                                                Y2 = pt2.Y + block2._area._area.MapSize / 2 + ix,
                                                Stroke = new SolidColorBrush(Color2.Orange(80)),
                                                StrokeThickness = 2
                                            });
                                            ix += 2;
                                        }
                                    }
                                }
                            }
                            #endregion
                        }
                    }
                }

            }
        }
        #endregion

        #region Area
        public class Area
        {
            public StarWindow _window = null;
            public comm.objst.DStar.Data.Area _area = null;
            public Block[,] _blocks = null;
            public Canvas _cvLayer = null;
            public Dictionary<string, List<int[]>> _dotDic = new Dictionary<string, List<int[]>>();

            int dotSize = 16;
            Grid _gridRoot = null;
            public Canvas _cvMask = null;

            public Area(StarWindow window, string areaKey)
            {
                _window = window;
                _area = _window._star.AreaDic[areaKey];

                _cvMask = new Canvas();

                _gridRoot = new Grid
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top,
                    MinWidth = 60,
                    MinHeight = 60,
                    Width = _area.Width * _area.MapSize,
                    Height = _area.Height * _area.MapSize,
                    Margin = new Thickness(_area.DesignX, _area.DesignY, 0, 0)
                };
                _gridRoot.Drag(AreaDrag);

                #region 4 dot
                _gridRoot.Children.Add(new Ellipse
                {
                    Width = dotSize,
                    Height = dotSize,
                    Margin = new Thickness(-dotSize / 2, -dotSize / 2, 0, 0),
                    Fill = new SolidColorBrush(Color2.White(50)),
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top
                });
                _gridRoot.Children.Add(new Ellipse
                {
                    Width = dotSize,
                    Height = dotSize,
                    Margin = new Thickness(0, -dotSize / 2, -dotSize / 2, 0),
                    Fill = new SolidColorBrush(Color2.White(50)),
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Top
                });
                _gridRoot.Children.Add(new Ellipse
                {
                    Width = dotSize,
                    Height = dotSize,
                    Margin = new Thickness(-dotSize / 2, 0, 0, -dotSize / 2),
                    Fill = new SolidColorBrush(Color2.White(50)),
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Bottom
                });
                _gridRoot.Children.Add(new Ellipse
                {
                    Width = dotSize,
                    Height = dotSize,
                    Margin = new Thickness(0, 0, -dotSize / 2, -dotSize / 2),
                    Fill = new SolidColorBrush(Color2.White(50)),
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Bottom
                });
                #endregion

                #region bg
                _gridRoot.Children.Add(new Border
                {
                    BorderBrush = new SolidColorBrush(Color2.White(10)),
                    BorderThickness = new Thickness(1),
                    Background = new SolidColorBrush(Color2.White(0))
                });
                #endregion

                if (_window.CanDisplay(LayerType.背景))
                {
                    #region bg
                    if (_area.BGImageBytes != null)
                    {
                        var bitmap = new BitmapImage();
                        bitmap.FromBytes(_area.BGImageBytes);
                        _gridRoot.Children.Add(new Image
                        {
                            Width = bitmap.PixelWidth,
                            Height = bitmap.PixelHeight,
                            Source = bitmap,
                            HorizontalAlignment = HorizontalAlignment.Left,
                            VerticalAlignment = VerticalAlignment.Top
                        });
                    }
                    #endregion
                }

                _cvLayer = new Canvas();
                _gridRoot.Children.Add(_cvLayer);

                #region contextMenu
                var contextMenu = new ContextMenu { FontSize = 14 };
                TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);

                var miEdit = new MenuItem { Header = "编辑Area" };
                miEdit.Click += new RoutedEventHandler((o, e) =>
                {
                    ReceiveCmd("editArea");
                });
                contextMenu.Items.Add(miEdit);

                _gridRoot.ContextMenu = contextMenu;
                #endregion

                _gridRoot.Children.Add(_cvMask);

                _window.gridLayer.Children.Add(_gridRoot);

                _blocks = new Block[_area.Width, _area.Height];
                for (int x = 0; x < _area.Width; x++)
                {
                    for (int y = 0; y < _area.Height; y++)
                    {
                        var space = _area.Spaces[x, y];
                        foreach (var item in space.PathList)
                        {
                            var key = item[0] + "," + item[1];
                            if (!_dotDic.ContainsKey(key))
                            {
                                _dotDic.Add(key, new List<int[]>());
                            }
                            _dotDic[key].Add(item);
                        }

                        var block = new Block(this, x, y);
                        block.Draw();
                        _blocks[x, y] = block;

                        if (!_window._blockDic.ContainsKey(space.SpaceId))
                        {
                            _window._blockDic.Add(space.SpaceId, block);
                        }
                    }
                }
            }

            void AreaDrag(FrameworkElement sender, MouseEventArgs e, string type, double ox, double oy)
            {
                var pt = e.GetPosition(_window.gridLayer);
                double x = pt.X, y = pt.Y;
                x -= ox;
                y -= oy;
                _gridRoot.Margin = new Thickness(x, y, 0, 0);
                _area.DesignX = (int)x;
                _area.DesignY = (int)y;
            }
            void SetSize(int w, int h)
            {
                var spaces = new comm.objst.DStar.Data.Space[w, h];
                for (int x = 0; x < w; x++)
                {
                    for (int y = 0; y < h; y++)
                    {
                        if (x < _area.Width && y < _area.Height)
                        {
                            spaces[x, y] = _area.Spaces[x, y];
                        }
                        else
                        {
                            spaces[x, y] = new comm.objst.DStar.Data.Space();
                        }
                    }
                }
                _area.Spaces = spaces;
                _area.Width = w;
                _area.Height = h;
            }

            public Point GetPosition()
            {
                return _gridRoot.TranslatePoint(new Point(), _window.gridRoot);
            }
            public void ReceiveCmd(string cmd, params object[] args)
            {
                if (cmd == "editArea")
                {
                    new AreaWindow(ReceiveCmd, _area).ShowDialog();
                }
                else if (cmd == "setSize")
                {
                    _area.MapSize = (int)args[2];
                    _area.MapBlockSize = (int)args[3];
                    SetSize((int)args[0], (int)args[1]);
                    _window.Fill();
                }
                else if (cmd == "makePath")
                {
                    var mesh = new comm.PolygonMesh(_area.Width, _area.Height, _area.MapSize, _area.MapBlockSize);
                    mesh.Splice();
                    var blocks = mesh.ToBlocks();
                    for (int x = 0; x < _area.Width; x++)
                    {
                        for (int y = 0; y < _area.Height; y++)
                        {
                            _area.Spaces[x, y].PathList = blocks[x, y];
                        }
                    }
                    _window.Fill();
                }
            }
            public void SetBG()
            {
                var ofd = new wf.OpenFileDialog();
                if (ofd.ShowDialog().ToString() == "OK")
                {
                    #region read bitmap
                    try
                    {
                        using (var bitmap = new dw.Bitmap(ofd.FileName))
                        {
                            using (var ms = new io.MemoryStream())
                            {
                                bitmap.Save(ms, dw.Imaging.ImageFormat.Png);
                                _area.BGImageBytes = ms.ToArray();
                            }
                        }
                        _window.Fill();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    #endregion
                }
            }
            public void ClearAllMapId()
            {
                for (int x = 0; x < _area.Width; x++)
                {
                    for (int y = 0; y < _area.Height; y++)
                    {
                        _area.Spaces[x, y].MapId = "";
                    }
                }
                _window.Fill();
            }
            public void SetAllSpaceType(comm.objst.SpaceType type)
            {
                for (int x = 0; x < _area.Width; x++)
                {
                    for (int y = 0; y < _area.Height; y++)
                    {
                        _area.Spaces[x, y].SpaceType = type;
                    }
                }
                _window.Fill();
            }
            public void SetSpaceLoc(int fromX, int fromY, int toX, int toY)
            {
                var key1 = fromX + "," + fromY; ;
                var key2 = toX + "," + toY;

                if (_dotDic.ContainsKey(key2))
                {
                    return;
                }

                var list = _dotDic[key1];
                foreach (var item in list)
                {
                    item[0] = toX;
                    item[1] = toY;
                }
                _dotDic.Remove(key1);
                _dotDic.Add(key2, list);

                for (int x = 0; x < _area.Width; x++)
                {
                    for (int y = 0; y < _area.Height; y++)
                    {
                        _blocks[x, y].DrawPath();
                    }
                }
            }
        }
        #endregion

        comm.objst.DStar.Data _star = null;
        string _fileName = "";
        string _sign = "";

        Dictionary<string, Area> _areaDic = new Dictionary<string, Area>();
        Dictionary<string, Block> _blockDic = new Dictionary<string, Block>();
        Dictionary<LayerType, CheckBox> _ckDic = new Dictionary<LayerType, CheckBox>();

        List<Border> _factionList = new List<Border>();
        List<CheckBox> _mapList = new List<CheckBox>();

        const string EXT_NAME = comm.objst.DStar.Data.FILE_EXT_NAME;

        public StarWindow(string fileName = null)
        {
            InitializeComponent();
            this.LoadConfig1();

            #region cks
            var type = typeof(LayerType);
            var ckNames = comm.EnumHelper.GetNames(type);
            foreach (var ckName in ckNames)
            {
                var t = (LayerType)Enum.Parse(type, ckName);
                var ck = new CheckBox
                {
                    Focusable = false,
                    Content = new TextBlock { Text = ckName },
                    Tag = ckName,
                    IsChecked = (int)t % 2 != 0,
                    Margin = new Thickness(4, 0, 0, 0),
                    VerticalAlignment = VerticalAlignment.Center
                };
                _ckDic.Add(t, ck);
                ck.Checked += new RoutedEventHandler(ck_Checked);
                ck.Unchecked += new RoutedEventHandler(ck_Checked);
                spCks.Children.Add(ck);
            }
            #endregion

            if (fileName != null)
            {
                _fileName = fileName;
                OpenFile();
            }

            KeyDown += new KeyEventHandler(StarWindow_KeyDown);
            btnNew.Click += new RoutedEventHandler(btnNew_Click);
            btnReload.Click += new RoutedEventHandler(btnReload_Click);
            btnNewFaction.Click += new RoutedEventHandler(btnNewFaction_Click);
            btnNewArea.Click += new RoutedEventHandler(btnNewArea_Click);
            btnMakeSpaceId.Click += new RoutedEventHandler(btnMakeSpaceId_Click);

            FillMap();

            #region loop
            comm.ThreadHelper.Run(() =>
            {
                while (true)
                {
                    if (_star != null)
                    {
                        var isChange = CheckSignChange();
                        Dispatcher.Invoke(new Action(() =>
                        {
                            Title = io.Path.GetFileName(_fileName) + (isChange ? "*" : "");
                            UpdateMask();
                        }));
                    }
                    Thread.Sleep(100);
                }
            });
            #endregion
        }

        void StarWindow_KeyDown(object sender, KeyEventArgs e)
        {
            var keyDic = new Dictionary<Key, LayerType>();
            keyDic.Add(Key.G, LayerType.网格);
            keyDic.Add(Key.T, LayerType.编号);
            keyDic.Add(Key.D, LayerType.拖动1);
            keyDic.Add(Key.E, LayerType.拖动2);
            keyDic.Add(Key.F, LayerType.阵营关系);
            keyDic.Add(Key.X, LayerType.地图关系);
            keyDic.Add(Key.A, LayerType.空间关系);

            if (Keyboard.Modifiers == ModifierKeys.Control)
            {
                if (e.Key == Key.S)
                {
                    SaveFile();
                }
                else if (e.Key == Key.Enter)
                {
                    foreach (var area in _areaDic.Values)
                    {
                        area._area.DesignX = 4;
                        area._area.DesignY = 4;
                    }
                    Fill();
                }

                if (keyDic.ContainsKey(e.Key))
                {
                    var lt = keyDic[e.Key];
                    _ckDic[lt].IsChecked = !_ckDic[lt].IsChecked;
                }
            }
        }
        void btnReload_Click(object sender, RoutedEventArgs e)
        {
            if (_fileName != null)
            {
                OpenFile();
            }
        }
        void btnNew_Click(object sender, RoutedEventArgs e)
        {
            var sfd = new wf.SaveFileDialog { Filter = EXT_NAME + "|*" + EXT_NAME };
            if (sfd.ShowDialog().ToString() == "OK")
            {
                _star = new comm.objst.DStar.Data();
                _fileName = sfd.FileName;
                SaveFile();
                OpenFile();
            }
        }
        void mEdit_Click(object sender, RoutedEventArgs e)
        {
            var mi = (MenuItem)sender;
            new MapWindow(mi.Tag.ToString()).ShowDialog();
            Fill();
        }

        void btnNewFaction_Click(object sender, RoutedEventArgs e)
        {
            _star.FactionDic.Add(comm.GUID.NewString(), new comm.objst.DStar.Data.Faction());
            FillFaction();
        }
        void btnFactionDel_Click(object sender, RoutedEventArgs e)
        {
            var key = ((Grid)((FrameworkElement)sender).Parent).Tag.ToString();
            _star.FactionDic.Remove(key);
            FillFaction();
        }
        void tbColor_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                var tb = (TextBox)sender;
                var key = ((Grid)tb.Parent).Tag.ToString();
                var fac = _star.FactionDic[key];
                var color = dw.ColorTranslator.FromHtml(tb.Text);

                fac.Color.A = color.A;
                fac.Color.R = color.R;
                fac.Color.G = color.G;
                fac.Color.B = color.B;
                FillFaction();
            }
        }
        void gridIco_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var key = ((Grid)((FrameworkElement)sender).Parent).Tag.ToString();
            var fac = _star.FactionDic[key];
            var ofd = new wf.OpenFileDialog();
            if (ofd.ShowDialog().ToString() == "OK")
            {
                #region read bitmap
                try
                {
                    using (var bitmap = new dw.Bitmap(ofd.FileName))
                    {
                        using (var ms = new io.MemoryStream())
                        {
                            bitmap.Save(ms, dw.Imaging.ImageFormat.Png);
                            fac.FlagImageBytes = ms.ToArray();
                        }
                    }
                    FillFaction();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                #endregion
            }
        }
        void tbFaction_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tb = (TextBox)sender;
            var parent = (Grid)tb.Parent;
            var key = parent.Tag.ToString();
            var ss = tb.Text.Split(',');
            if (ss.Length == 2)
            {
                var newKey = ss[0].Trim();
                var name = ss[1].Trim();
                var b = _star.FactionDic[key];
                b.Name = name;
                tb.Opacity = 1;
                if (key != newKey)
                {
                    if (!_star.FactionDic.ContainsKey(newKey))
                    {
                        _star.FactionDic.Remove(key);
                        _star.FactionDic.Add(newKey, b);
                        key = newKey;
                        parent.Tag = key;
                    }
                    else
                    {
                        tb.Opacity = .6;
                    }
                }
            }
            else
            {
                tb.Opacity = .6;
            }
        }

        void btnNewArea_Click(object sender, RoutedEventArgs e)
        {
            _star.AreaDic.Add(comm.GUID.NewString(), new comm.objst.DStar.Data.Area());
            FillArea();
            Fill();
        }
        void btnAreaDel_Click(object sender, RoutedEventArgs e)
        {
            var key = ((Grid)((FrameworkElement)sender).Parent).Tag.ToString();
            _star.AreaDic.Remove(key);
            FillArea();
            Fill();
        }
        void tbArea_TextChanged(object sender, TextChangedEventArgs e)
        {
            var tb = (TextBox)sender;
            var parent = (Grid)tb.Parent;
            var key = parent.Tag.ToString();
            var newKey = tb.Text.Trim();
            tb.Opacity = 1;
            var b = _star.AreaDic[key];
            if (key != newKey)
            {
                if (!_star.AreaDic.ContainsKey(newKey))
                {
                    _star.AreaDic.Remove(key);
                    _star.AreaDic.Add(newKey, b);
                    key = newKey;
                    parent.Tag = key;
                }
                else
                {
                    tb.Opacity = .6;
                }
            }
        }

        void ck_Checked(object sender, RoutedEventArgs e)
        {
            Fill();
        }

        void tbStartId_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnMakeSpaceId_Click(btnMakeSpaceId, new RoutedEventArgs());
            }
        }
        void btnMakeSpaceId_Click(object sender, RoutedEventArgs e)
        {
            uint six = 0;
            if (uint.TryParse(tbStartId.Text, out six))
            {
                _star.SpaceStartId = (int)six;

                foreach (var area in _star.AreaDic.Values)
                {
                    for (int x = 0; x < area.Width; x++)
                    {
                        for (int y = 0; y < area.Height; y++)
                        {
                            area.Spaces[x, y].SpaceId = six.ToString();
                            six++;
                        }
                    }
                }
            }
            Fill();
        }

        void UpdateMask()
        {
            cvLine.Children.Clear();

            if (CanDisplay(LayerType.空间关系))
            {
                foreach (var block in _blockDic.Values)
                {
                    block.LinkSpace(cvLine);
                }
            }

            if (CanDisplay(LayerType.阵营关系) && tabView.SelectedIndex == 0)
            {
                #region Faction
                foreach (var br in _factionList)
                {
                    var fac = (comm.objst.DStar.Data.Faction)br.Tag;
                    var pt = br.TranslatePoint(new Point(), gridRoot);
                    foreach (var spaceId in fac.BaseSpaceIdList)
                    {
                        if (!_blockDic.ContainsKey(spaceId))
                        {
                            break;
                        }
                        var block = _blockDic[spaceId];
                        var blockPosition = block.GetPosition();
                        var pt3 = block._area.GetPosition();

                        #region path
                        var path = block.MakePath();
                        path.Stroke = new SolidColorBrush(Color2.Red(70));
                        path.StrokeThickness = 2;
                        path.SetLeftTop(pt3.X, pt3.Y);
                        cvLine.Children.Add(path);
                        #endregion

                        #region line
                        cvLine.Children.Add(new Line
                        {
                            X1 = pt.X + 20,
                            Y1 = pt.Y + 10,
                            X2 = blockPosition.X + block._area._area.MapSize / 2,
                            Y2 = blockPosition.Y + block._area._area.MapSize / 2,
                            Stroke = new SolidColorBrush(Color2.Red(70)),
                            StrokeThickness = 2
                        });
                        #endregion
                    }
                }
                #endregion
            }
            else if (CanDisplay(LayerType.地图关系) && tabView.SelectedIndex == 1)
            {
                #region map
                foreach (var ck in _mapList)
                {
                    var mapId = ck.Tag.ToString();
                    if (ck.IsChecked == true)
                    {
                        var pt = ck.TranslatePoint(new Point(), gridRoot);
                        foreach (var block in _blockDic.Values)
                        {
                            if (block._space.MapId == mapId)
                            {
                                var blockPosition = block.GetPosition();
                                var pt3 = block._area.GetPosition();

                                #region path
                                var path = block.MakePath();
                                path.Stroke = new SolidColorBrush(Color2.Red(70));
                                path.StrokeThickness = 2;
                                path.SetLeftTop(pt3.X, pt3.Y);
                                cvLine.Children.Add(path);
                                #endregion

                                #region line
                                cvLine.Children.Add(new Line
                                {
                                    X1 = pt.X + 20,
                                    Y1 = pt.Y + 10,
                                    X2 = blockPosition.X + block._area._area.MapSize / 2,
                                    Y2 = blockPosition.Y + block._area._area.MapSize / 2,
                                    Stroke = new SolidColorBrush(Color2.Red(70)),
                                    StrokeThickness = 2
                                });
                                #endregion
                            }
                        }
                    }
                }
                #endregion
            }
            if (_chooseBlock != null && Mouse.LeftButton == MouseButtonState.Pressed)
            {
                var dpt = Mouse.GetPosition(gridRoot);
                var blockPosition = _chooseBlock.GetPosition();
                cvLine.Children.Add(new Line
                {
                    X1 = _choosePt.X - 4,
                    Y1 = _choosePt.Y - 4,
                    X2 = dpt.X - 4,
                    Y2 = dpt.Y - 4,
                    Stroke = new SolidColorBrush(Color2.Red(50)),
                    StrokeThickness = 2
                });
            }
            else
            {
                var tblock = _chooseBlock;
                var dblock = _enterBlock;
                _chooseBlock = null;

                if (tblock != null &&
                    dblock != null &&
                    tblock._map != null &&
                    dblock._map != null)
                {
                    comm.ThreadHelper.Run(() =>
                    {
                        Thread.Sleep(500);
                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            var spaces = new comm.objst.DStar.Data.Space[2, 1];
                            spaces[0, 0] = tblock._space;
                            spaces[1, 0] = dblock._space;
                            new SpaceLinkWindow(2, 1, spaces).ShowDialog();
                            Fill();
                        }));
                    });
                }
            }
        }
        bool CanDisplay(LayerType type)
        {
            return _ckDic[type].IsChecked == true;
        }
        void MapDrag(FrameworkElement sender, MouseEventArgs e, string type, double ox, double oy)
        {
            var pt2 = e.GetPosition(gridRoot);
            var block = FindBlock(pt2);
            if (block != null)
            {
                block.Light();
            }

            if (type == "move")
            {
                brDragIcon.Visibility = Visibility.Visible;
            }
            else if (type == "up")
            {
                brDragIcon.Visibility = Visibility.Collapsed;
                if (block != null)
                {
                    var grid = (Grid)sender;
                    block.SetMap(grid.Tag.ToString());
                    Fill();
                }
            }
            var pt = e.GetPosition(gridRoot);
            brDragIcon.Margin = new Thickness(pt.X - brDragIcon.Width / 2, pt.Y - brDragIcon.Width / 2, 0, 0);
        }
        void FactionDrag(FrameworkElement sender, MouseEventArgs e, string type, double ox, double oy)
        {
            var pt2 = e.GetPosition(gridRoot);
            var block = FindBlock(pt2);
            if (block != null)
            {
                block.Light();
            }

            if (type == "move")
            {
                brDragIcon.Visibility = Visibility.Visible;
            }
            else if (type == "up")
            {
                var br = (Border)sender;
                var parent = (Grid)br.Parent;
                brDragIcon.Visibility = Visibility.Collapsed;
                if (block != null)
                {
                    var list = _star.FactionDic[parent.Tag.ToString()].BaseSpaceIdList;
                    if (!list.Contains(block._space.SpaceId))
                    {
                        list.Add(block._space.SpaceId);
                    }
                    FillFaction();
                }
            }
            var pt = e.GetPosition(gridRoot);
            brDragIcon.Margin = new Thickness(pt.X - brDragIcon.Width / 2, pt.Y - brDragIcon.Width / 2, 0, 0);
        }
        Block FindBlock(Point pt)
        {
            foreach (var block in _blockDic.Values)
            {
                if (block.PointInPolygon((int)pt.X, (int)pt.Y))
                {
                    return block;
                }
            }
            return null;
        }
        void BlockClick(Block block)
        {
            _choosePt = Mouse.GetPosition(gridRoot);
            _chooseBlock = block;
        }
        void BlockEnter(Block block)
        {
            _enterBlock = block;
        }
        Block _chooseBlock = null;
        Point _choosePt;
        Block _enterBlock = null;

        void FillMap()
        {
            spMap.Children.Clear();
            _mapList.Clear();

            var maps = App.DefineFile.GetAllMap();
            foreach (var mapId in maps)
            {
                var grid = new Grid { Tag = mapId };
                grid.Drag(MapDrag);

                #region icon
                var bitmap = new BitmapImage();
                bitmap.FromFile("icon/map.png");
                grid.Children.Add(new Image
                {
                    Source = bitmap,
                    Width = bitmap.PixelWidth,
                    Height = bitmap.PixelHeight,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Center
                });
                #endregion

                grid.Children.Add(new TextBlock
                {
                    Text = mapId,
                    Margin = new Thickness(20, 0, 26, 0),
                    VerticalAlignment = VerticalAlignment.Center
                });

                #region ck
                var ck = new CheckBox
                {
                    IsChecked = true,
                    Focusable = false,
                    Tag = mapId,
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Center
                };
                _mapList.Add(ck);
                grid.Children.Add(ck);
                #endregion

                #region contextMenu
                var contextMenu = new ContextMenu { FontSize = 14 };
                TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);
                var map = App.DefineFile.GetMap(mapId);
                var mEdit = new MenuItem { Tag = map.File, Header = new TextBlock { Text = "Edit Map" } };
                mEdit.Click += new RoutedEventHandler(mEdit_Click);
                contextMenu.Items.Add(mEdit);

                grid.ContextMenu = contextMenu;
                #endregion

                spMap.Children.Add(grid);
            }
        }
        void Fill()
        {
            tbStartId.Text = _star.SpaceStartId.ToString();

            _areaDic.Clear();
            _blockDic.Clear();
            gridLayer.Children.Clear();
            foreach (var key in _star.AreaDic.Keys)
            {
                _areaDic.Add(key, new Area(this, key));
            }

            #region verify BaseSpaceIdList
            var change = false;
            foreach (var fac in _star.FactionDic.Values)
            {
                for (int i = 0, len = fac.BaseSpaceIdList.Count; i < len; i++)
                {
                    var spaceId = fac.BaseSpaceIdList[i];
                    if (!_blockDic.ContainsKey(spaceId))
                    {
                        change = true;
                        fac.BaseSpaceIdList.Remove(spaceId);
                        len--;
                        i--;
                    }
                }
            }
            if (change)
            {
                FillFaction();
            }
            #endregion
        }
        void FillFaction()
        {
            spFaction.Children.Clear();
            _factionList.Clear();

            var icoSize = 30;

            foreach (var facKey in _star.FactionDic.Keys)
            {
                var fac = _star.FactionDic[facKey];
                var grid = new Grid { Tag = facKey, Margin = new Thickness(0, 4, 0, 0) };
                var color = Color.FromArgb(fac.Color.A, fac.Color.R, fac.Color.G, fac.Color.B);

                #region gridIco
                var gridIco = new Grid
                {
                    Height = icoSize,
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top,
                    Background = new SolidColorBrush(Color2.Transparent())
                };
                gridIco.Children.Add(new Border
                {
                    Child = new TextBlock
                    {
                        Text = "Set Icon",
                        Foreground = new SolidColorBrush(Color2.White())
                    },
                    Background = new SolidColorBrush(Color2.Black()),
                    VerticalAlignment = VerticalAlignment.Bottom
                });
                if (fac.FlagImageBytes != null)
                {
                    var bitmap = new BitmapImage();
                    bitmap.FromBytes(fac.FlagImageBytes);
                    gridIco.Children.Clear();
                    gridIco.Children.Add(new Image
                    {
                        Width = bitmap.PixelWidth,
                        MaxHeight = bitmap.PixelHeight,
                        Source = bitmap,
                        Height = icoSize
                    });

                    gridIco.Width = bitmap.PixelWidth;
                    gridIco.Height = bitmap.PixelHeight;
                    gridIco.Background = new SolidColorBrush(color);
                }
                gridIco.MouseLeftButtonDown += new MouseButtonEventHandler(gridIco_MouseLeftButtonDown);
                grid.Children.Add(gridIco);
                #endregion

                #region tbFaction
                var tbFaction = new TextBox
                {
                    Text = facKey + "," + fac.Name,
                    Padding = new Thickness(0),
                    TextWrapping = TextWrapping.Wrap,
                    BorderThickness = new Thickness(0, 0, 0, 1),
                    BorderBrush = new SolidColorBrush(Color2.Black(50)),
                    Height = 22,
                    Margin = new Thickness(26, icoSize, 70, 0)
                };
                tbFaction.TextChanged += new TextChangedEventHandler(tbFaction_TextChanged);
                grid.Children.Add(tbFaction);
                #endregion

                #region btnFactionDel
                var btnFactionDel = new Button
                {
                    Focusable = false,
                    Width = 22,
                    Height = 22,
                    Content = "X",
                    Margin = new Thickness(0, icoSize, 0, 0),
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top
                };
                btnFactionDel.Click += new RoutedEventHandler(btnFactionDel_Click);
                grid.Children.Add(btnFactionDel);
                #endregion

                #region tbColor
                var tbColor = new TextBox
                {
                    Width = 40,
                    Height = 22,
                    FontSize = 12,
                    Padding = new Thickness(0),
                    Text = dw.ColorTranslator.ToHtml(dw.Color.FromArgb(fac.Color.A, fac.Color.R, fac.Color.G, fac.Color.B)),
                    Margin = new Thickness(0, icoSize, 24, 0),
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Top
                };
                tbColor.KeyDown += new KeyEventHandler(tbColor_KeyDown);
                grid.Children.Add(tbColor);
                #endregion

                #region brDrag
                var brDrag = new Border
                {
                    Tag = fac,
                    Child = new TextBlock
                    {
                        Text = fac.BaseSpaceIdList.Count.ToString(),
                        Foreground = new SolidColorBrush(Color2.White()),
                        FontSize = 12,
                        VerticalAlignment = VerticalAlignment.Center,
                        HorizontalAlignment = HorizontalAlignment.Center
                    },
                    Width = 22,
                    Height = 22,
                    Margin = new Thickness(0, icoSize, 0, 0),
                    CornerRadius = new CornerRadius(22),
                    Background = new SolidColorBrush(Color2.Black()),
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Top
                };

                _factionList.Add(brDrag);

                brDrag.Drag(FactionDrag);
                grid.Children.Add(brDrag);
                #endregion

                #region contextMenu
                var contextMenu = new ContextMenu { FontSize = 14 };
                TextOptions.SetTextFormattingMode(contextMenu, TextFormattingMode.Display);

                #region mClear
                var mClear = new MenuItem { Header = new TextBlock { Text = "Clear" } };
                mClear.Click += new RoutedEventHandler((o, e) =>
                {
                    fac.BaseSpaceIdList.Clear();
                    FillFaction();
                });
                contextMenu.Items.Add(mClear);
                #endregion

                brDrag.ContextMenu = contextMenu;
                #endregion

                spFaction.Children.Add(grid);
            }
        }
        void FillArea()
        {
            spArea.Children.Clear();

            foreach (var areaKey in _star.AreaDic.Keys)
            {
                var item = _star.AreaDic[areaKey];
                var grid = new Grid { Tag = areaKey, Margin = new Thickness(0, 4, 0, 0) };

                #region tbArea
                var tbArea = new TextBox
                {
                    Text = areaKey,
                    Padding = new Thickness(0),
                    TextWrapping = TextWrapping.Wrap,
                    BorderThickness = new Thickness(0, 0, 0, 1),
                    BorderBrush = new SolidColorBrush(Color2.Black(50)),
                    Height = 22,
                    Margin = new Thickness(26, 0, 0, 0)
                };
                tbArea.TextChanged += new TextChangedEventHandler(tbArea_TextChanged);
                grid.Children.Add(tbArea);
                #endregion

                #region btnAreaDel
                var btnAreaDel = new Button
                {
                    Focusable = false,
                    Width = 22,
                    Height = 22,
                    Content = "X",
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top
                };
                grid.Children.Add(btnAreaDel);
                btnAreaDel.Click += new RoutedEventHandler(btnAreaDel_Click);
                #endregion

                if (areaKey == comm.objst.DStar.Data.DEFAULT_AREA_KEY)
                {
                    btnAreaDel.IsEnabled = false;
                    tbArea.IsReadOnly = true;
                }

                spArea.Children.Add(grid);
            }
        }

        void SaveFile()
        {
            try
            {
                var bytes = comm.BinarySerializer.Serialize(_star);
                io.File.WriteAllBytes(_fileName, bytes);
                MakeSign();
            }
            catch (Exception ex)
            {
                MessageBox.Show("save file:" + _fileName + " err!" + ex.Message);
            }
        }
        void OpenFile()
        {
            try
            {
                _star = comm.BinarySerializer.Deserialize<comm.objst.DStar.Data>(io.File.ReadAllBytes(_fileName));
                MakeSign();
                Fill();
                FillFaction();
                FillArea();
            }
            catch (Exception ex)
            {
                MessageBox.Show("open file:" + _fileName + " err!" + ex.Message);
            }
        }
        void MakeSign()
        {
            _sign = comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_star));
        }
        bool CheckSignChange()
        {
            return _sign != comm.Safety.SHA1Encode(comm.BinarySerializer.Serialize(_star));
        }
    }
}
